package com.mathassistant.client.presenter;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.mathassistant.client.event.ShowTopicPopupEvent;
import com.mathassistant.client.event.ToAdminViewEvent;
import com.mathassistant.client.event.ToAdminViewEventHandler;
import com.mathassistant.client.event.ToUserViewEvent;
import com.mathassistant.client.event.ToUserViewEventHandler;
import com.mathassistant.client.event.topic.TopicAddEvent;
import com.mathassistant.client.event.topic.TopicChoosedEvent;
import com.mathassistant.client.event.topic.TopicListUpdateEvent;
import com.mathassistant.client.event.topic.TopicListUpdateEventHandler;
import com.mathassistant.client.helper.ClickPoint;
import com.mathassistant.client.helper.RPCCall;
import com.mathassistant.client.service.TopicServiceAsync;
import com.mathassistant.shared.TopicDTO;

public class TopicListPresenter implements Presenter {

	private List<TopicDTO> topics;
	private int selectedRow;
	
	private final String area;
	private final String contentType;
	
	private final TopicServiceAsync rpcService;
	private final SimpleEventBus eventBus;
	private final Display display;

	public interface Display {
		HasClickHandlers getHyperlinkAddTopic();

		HasClickHandlers getListTopics();

		void setData(List<String> topics);
		
		void resetData();

		int getClickedRow(ClickEvent event);

		ClickPoint getClickedPoint(ClickEvent event);

		Widget asWidget();

		int getClickedPropertyButton(ClickEvent event);
		
		void setToAdminView();
		
		void setToUserView(); 
	}

	public Display getDisplay(){
		return display;
	}
	
	public TopicListPresenter(String area, String contentType, TopicServiceAsync rpcService,
			SimpleEventBus eventBus, Display view) {
		this.area = area;
		this.contentType = contentType;
		this.rpcService = rpcService;
		this.eventBus = eventBus;
		this.display = view;
		bind();
	}

	private void bind() {
		// TODO Auto-generated method stub
		display.getHyperlinkAddTopic().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				// TODO Auto-generated method stub
				eventBus.fireEvent(new TopicAddEvent(area,contentType));
			}
		});

		if (display.getListTopics() != null) {
			display.getListTopics().addClickHandler(new ClickHandler() {

				@Override
				public void onClick(ClickEvent event) {
					int propClicked = display.getClickedPropertyButton(event);
					GWT.log("Topic list clicked");
					if (propClicked >= 0) {
						GWT.log("Topic list property clicked");
						ClickPoint point = display.getClickedPoint(event);
						TopicDTO topic = topics.get(propClicked);
						eventBus.fireEvent(new ShowTopicPopupEvent(topic, point));
					} else {
						GWT.log("Topic list clicked");						
						selectedRow = display.getClickedRow(event);							
						eventBus.fireEvent(new TopicChoosedEvent(topics.get(selectedRow)));
					}
				}
			});
		}

		// listen
		eventBus.addHandler(TopicListUpdateEvent.TYPE,
				new TopicListUpdateEventHandler() {

					@Override
					public void onTopicUpdate(TopicListUpdateEvent event) {
						// TODO Auto-generated method stub
						if( (area.equals(event.getArea())) && (contentType.equals(event.getContentType()))){
							fetchTopicDTO();
						}						
					}
				});	
		
		eventBus.addHandler(ToAdminViewEvent.TYPE, new ToAdminViewEventHandler() {
			
			@Override
			public void onTopicListToAdminView(ToAdminViewEvent event) {
				// TODO Auto-generated method stub
				display.setToAdminView();
				if(topics != null)
					display.setData(toStringList(topics));
			}
		});
		
		eventBus.addHandler(ToUserViewEvent.TYPE, new ToUserViewEventHandler() {
			
			@Override
			public void onTopicListToUserView(ToUserViewEvent event) {
				// TODO Auto-generated method stub
				display.setToUserView();
				if(topics != null)
					display.setData(toStringList(topics));
			}
		});
	}

	@Override
	public void go(HasWidgets container) {
		// TODO Auto-generated method stub
		container.clear();
		container.add(display.asWidget());
		fetchTopicDTO();
	}

	private void fetchTopicDTO() {
		// TODO Auto-generated method stub
		new RPCCall<ArrayList<TopicDTO>>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				Window.alert("Error fetching topics: " + caught.getMessage());
			}

			@Override
			public void onSuccess(ArrayList<TopicDTO> result) {
				// TODO Auto-generated method stub
				topics = result;
				if(topics == null || topics.size() == 0){
					display.resetData();
					return;
				}
				sortTopicDTO();
				display.setData(toStringList(topics));
			}

			@Override
			protected void callService(AsyncCallback<ArrayList<TopicDTO>> cb) {
				// TODO Auto-generated method stub
				rpcService.getTopics(area, contentType, cb);
			}
		}.retry(3);
		
	}

	@Override
	public void go() {}

	private List<String> toStringList(List<TopicDTO> topics) {
		// TODO Auto-generated method stub
		List<String> list = new ArrayList<String>();
		for (TopicDTO topicDTO : topics) {
			list.add(topicDTO.getContent());
		}
		return list;
	}

	private void sortTopicDTO() {
		// TODO Auto-generated method stub
		for (int i = 0; i < topics.size(); ++i) {
			for (int j = 0; j < topics.size() - 1; ++j) {
				if (topics.get(j).getContent()
						.compareToIgnoreCase(topics.get(j + 1).getContent()) >= 0) {
					TopicDTO tmp = topics.get(j);
					topics.set(j, topics.get(j + 1));
					topics.set(j + 1, tmp);
				}
			}
		}
	}

	public String getArea() {
		return area;
	}

	public String getContentType() {
		return contentType;
	}
}
